const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`;
const qnameCapture = `((?:${ncname}\\:)?${ncname})`;
const startTagOpen = new RegExp(`^<${qnameCapture}`);
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`);
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;
const startTagClose = /^\s*(\/?)>/;
export function parseHTML(html) { //这个函数的作用是取标签
  const ELEMENT_TYPE = 1;
  const TEXT_TYPE = 3;
  const stack = [];
  let currentParent;
  let root;
  function createASTElement(tag, attrs) {
    return {
      tag,
      type: ELEMENT_TYPE,
      children: [],
      attrs,
      parent: null
    }
  }
  //利用栈型结构来构造一棵树
  function start(tag, attrs) {//拿到开始标签
    let node = createASTElement(tag, attrs);
    if (!root) {
      root = node;
    }
    if (currentParent) {
      node.parent = currentParent;
      currentParent.children.push(node);
    }
    stack.push(node);
    currentParent = node;
  }
  function chars(text) { //拿到文本
    text = text.replace(/\s/g, '');
    text && currentParent.children.push({
      type: TEXT_TYPE,
      text,
      parent: currentParent
    })
  }
  function end(tag) { //拿到结束标签
    let node = stack.pop();
    currentParent = stack[stack.length - 1];
  }
  function advance(n) {
    html = html.substring(n);
  }
  function parseStartTag() {
    const start = html.match(startTagOpen);
    if (start) {
      const match = {
        tagName: start[1],
        attrs: []
      }
      advance(start[0].length)
      let attr, end;
      while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
        advance(attr[0].length);
        match.attrs.push({ name: attr[1], value: attr[3] || attr[4] || attr[5] || true });
      }
      if (end) {
        advance(end[0].length);
      }
      return match;
    }
  }
  while (html) {
    let textEnd = html.indexOf('<');
    if (textEnd == 0) {
      const startTagMatch = parseStartTag();
      if (startTagMatch) { //解析开始标签
        start(startTagMatch.tagName, startTagMatch.attrs);
        continue
      }
      let endTagMach = html.match(endTag);
      if (endTagMach) { //解析结束标签
        advance(endTagMach[0].length);
        end(endTagMach[1]);
        continue
      }
    }
    if (textEnd > 0) {
      let text = html.substring(0, textEnd);
      if (text) { //文本内容
        chars(text)
        advance(text.length);
      }
    }
  }
  return root;
}